﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Reflection;
using TouchRC.Logic;
using TouchRC.Classes;
using TouchRC.Logging;

namespace TouchRC.Logic
{
    public static class ConfigSettings
    {
        public static List<ComputerListBoxItem> GetComputers()
        {
            List<ComputerListBoxItem> loadedComputers = new List<ComputerListBoxItem>();
            try
            {
                using (XmlReader reader = XmlReader.Create(SettingsFile.FullName))
                {
                    XDocument settingsDoc = XDocument.Load(reader);
                    var settings = from connectionElement in settingsDoc.Descendants("Computer")
                                   select new ComputerListBoxItem
                                   {
                                       Name = connectionElement.Element("Name").Value,
                                       DnsAddress = connectionElement.Element("DnsAddress").Value,
                                       RemotePort = GetIntFromXElement(connectionElement.Element("RemotePort")),
                                       ListeningPort = GetIntFromXElement(connectionElement.Element("ListenerPort")),
                                       Id = GetIntFromXElement(connectionElement.Element("Id")),
                                       MetadataCacheDir = GetFileInfoFromElement(connectionElement.Element("MetadataCacheDir"))
                                   };

                    if (settings != null && settings.Count() > 0)
                    {
                        foreach (ComputerListBoxItem computer in settings)
                        {
                            loadedComputers.Add(computer);
                        }
                    }
                }
            }
            catch(Exception e)
            {
                Logger.LogMessage("Error reading computers from xml file: {0}", e.Message);
            }
            return loadedComputers;
        }

        private static DirectoryInfo GetFileInfoFromElement(XElement xElement)
        {
            DirectoryInfo retVal = null;

            try
            {
                retVal = new DirectoryInfo(xElement.Value);
            }
            catch
            {
            }

            return retVal;
        }

        private static int GetIntFromXElement(XElement element)
        {
            int retVal = 0;
            if (element != null)
            {
                retVal = Int32.Parse(element.Value);
            }
            return retVal;
        }

        public static void AddComputerConfigs(ComputerListBoxItem computer)
        {
            List<ComputerListBoxItem> computers = GetComputers();
            computer.Id = GetNextFreeId();
            computers.Add(computer);
            SaveConfigs(computers);
        }

        public static int GetNextFreeId()
        {
            List<ComputerListBoxItem> computers = GetComputers();
            int currMax = 0;
            foreach (ComputerListBoxItem compy in computers)
            {
                if (compy.Id > currMax)
                    currMax = compy.Id;
            }

            return currMax + 1;
        }

        public static void UpdateComputerConfigs(ComputerListBoxItem computer)
        {
            List<ComputerListBoxItem> computers = GetComputers();
            for (int i = 0; i < computers.Count; i++)
            {
                if (computers[i].Id == computer.Id)
                {
                    computers[i] = computer;
                    break;
                }
            }
            SaveConfigs(computers);
        }

        public static void RemoveComputerConfigs(ComputerListBoxItem computer)
        {
            List<ComputerListBoxItem> newList = new List<ComputerListBoxItem>();
            List<ComputerListBoxItem> oldList = GetComputers();
            foreach (ComputerListBoxItem compy in oldList)
            {
                if (computer.Id != compy.Id)
                {
                    newList.Add(compy);
                }
            }
            SaveConfigs(newList);
        }

        public static void SaveConfigs(List<ComputerListBoxItem> computers)
        {
            using (XmlTextWriter xmlWriter = new XmlTextWriter(SettingsFile.FullName, Encoding.UTF8))
            {
                xmlWriter.WriteStartDocument();
                xmlWriter.WriteStartElement("ApplicationSettings");
                xmlWriter.WriteStartElement("UserSettings");
                xmlWriter.WriteElementString("BacklightAlwaysOn", AppSettings.BacklightAlwaysOn.ToString());
                xmlWriter.WriteElementString("Log", AppSettings.Log.ToString());
                xmlWriter.WriteEndElement();// UserSettings
                xmlWriter.WriteStartElement("ComputerList");
                foreach (ComputerListBoxItem compy in computers)
                {
                    xmlWriter.WriteStartElement("Computer");
                    xmlWriter.WriteElementString("Name", compy.Name);
                    xmlWriter.WriteElementString("Id", compy.Id.ToString());
                    xmlWriter.WriteElementString("DnsAddress", compy.DnsAddress);
                    xmlWriter.WriteElementString("RemotePort", compy.RemotePort.ToString());
                    xmlWriter.WriteElementString("ListenerPort", compy.ListeningPort.ToString());
                    xmlWriter.WriteElementString("MetadataCacheDir", compy.MetadataCacheDir == null ? string.Empty : compy.MetadataCacheDir.FullName);
                }
                xmlWriter.WriteEndDocument();
            }
        }

        public static DirectoryInfo ProgramDirectory
        {
            get
            {
                return new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase));
            }
        }

        public static FileInfo SettingsFile
        {
            get
            {
                return new FileInfo(Path.Combine(ProgramDirectory.FullName,
                "settings.xml"));
            }
        }
    }
}
